home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / INTERNET / SITES / LITTLE / P3SRC.ZIP / ATARI / OPTIN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-27  |  56.2 KB  |  2,398 lines

  1. /****************************************************************************
  2. *                   optin.c
  3. *
  4. *  This module contains functions for ini-file/command line parsing, streams.
  5. *
  6. *  from Persistence of Vision(tm) Ray Tracer
  7. *  Copyright 1996 Persistence of Vision Team
  8. *---------------------------------------------------------------------------
  9. *  NOTICE: This source code file is provided so that users may experiment
  10. *  with enhancements to POV-Ray and to port the software to platforms other
  11. *  than those supported by the POV-Ray Team.  There are strict rules under
  12. *  which you are permitted to use this file.  The rules are in the file
  13. *  named POVLEGAL.DOC which should be distributed with this file. If
  14. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  15. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  16. *  Forum.  The latest version of POV-Ray may be found there as well.
  17. *
  18. * This program is based on the popular DKB raytracer version 2.12.
  19. * DKBTrace was originally written by David K. Buck.
  20. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  21. *
  22. *****************************************************************************/
  23.  
  24. /****************************************************************************
  25. *
  26. *  This file contains the routines to implement an .INI file parser that can
  27. *  parse options in the form "Variable=value" or traditional POV-Ray
  28. *  command-line switches.  Values can come from POVRAYOPT, command-line,
  29. *  .DEF or .INI files.
  30. *
  31. *  Written by CEY 4/94 based on existing code and INI code from CDW.
  32. *
  33. *  ---
  34. *
  35. *****************************************************************************/
  36.  
  37. #include <ctype.h>
  38. #include <time.h>
  39. #include "frame.h"
  40. #include "povproto.h"
  41. #include "bbox.h"
  42. #include "lighting.h"
  43. #include "mem.h"        /*POV_FREE*/
  44. #include "octree.h"
  45. #include "povray.h"
  46. #include "optin.h"
  47. #include "optout.h"
  48. #include "parse.h"
  49. #include "radiosit.h"
  50. #include "render.h"
  51. #include "tokenize.h"
  52. #include "vlbuffer.h"
  53. #include "ppm.h"
  54. #include "targa.h"
  55. #include "userio.h"
  56. #include "png_pov.h"
  57.  
  58.  
  59.  
  60. /*****************************************************************************
  61. * Local preprocessor defines
  62. ******************************************************************************/
  63.  
  64.  
  65. /*****************************************************************************
  66. * Local typedefs
  67. ******************************************************************************/
  68.  
  69.  
  70.  
  71. /*****************************************************************************
  72. * Local variables
  73. ******************************************************************************/
  74.  
  75. char *DefaultFile[] =
  76. {
  77.   "debug.out",
  78.   "fatal.out",
  79.   "render.out",
  80.   "stats.out",
  81.   "warning.out",
  82.   "alltext.out"
  83. };
  84.  
  85. int inflag, outflag;
  86.  
  87. /* Quality constants */
  88.  
  89. long Quality_Values[12]=
  90. {
  91.   QUALITY_0, QUALITY_1, QUALITY_2, QUALITY_3, QUALITY_4,
  92.   QUALITY_5, QUALITY_6, QUALITY_7, QUALITY_8, QUALITY_9
  93. };
  94.  
  95. /* Keywords for the ini-file parser. */
  96.  
  97. struct Reserved_Word_Struct Option_Variable [] =
  98. {
  99.   { ALL_CONSOLE_OP, "All_Console" },
  100.   { ALL_FILE_OP, "All_File" },
  101.   { ANTIALIAS_DEPTH_OP, "Antialias_Depth" },
  102.   { ANTIALIAS_OP, "Antialias" },
  103.   { ANTIALIAS_THRESH_OP, "Antialias_Threshold" },
  104.   { BOUNDING_OP, "Bounding" },
  105.   { BOUNDING_THRESH_OP, "Bounding_Threshold" },
  106.   { BUFFERED_OUTPUT_OP,"Buffer_Output" },
  107.   { BUF_SIZE_OP, "Buffer_Size" },
  108.   { CLOCK_OP, "Clock" },
  109.  
  110.   { CONTINUE_OP, "Continue_Trace" },
  111.   { CREATE_INI_OP, "Create_Ini" },
  112.   { CYCLIC_ANIMATION_OP, "Cyclic_Animation" },
  113.   { DEBUG_CONSOLE_OP, "Debug_Console" },
  114.   { DEBUG_FILE_OP, "Debug_File" },
  115.   { DISPLAY_OP, "Display" },
  116.   { DISPLAY_GAMMA_OP, "Display_Gamma" },
  117.   { DRAW_VISTAS_OP, "Draw_Vistas" },
  118.   { END_COLUMN_OP, "End_Column" },
  119.   { END_ROW_OP, "End_Row" },
  120.   { FATAL_CONSOLE_OP, "Fatal_Console" },
  121.  
  122.   { FATAL_ERROR_CMD_OP, "Fatal_Error_Command" },
  123.   { FATAL_ERROR_RET_OP, "Fatal_Error_Return" },
  124.   { FATAL_FILE_OP, "Fatal_File" },
  125.   { FIELD_RENDER_OP, "Field_Render" },
  126.   { FILE_OUTPUT_OP, "Output_to_File" },
  127.   { FILE_OUTPUT_TYPE_OP, "Output_File_Type" },
  128.   { FINAL_CLOCK_OP, "Final_Clock" },
  129.   { FINAL_FRAME_OP, "Final_Frame" },
  130.   { HEIGHT_OP, "Height" },
  131.   { HIST_NAME_OP, "Histogram_Name" },
  132.  
  133.   { HIST_SIZE_OP, "Histogram_Grid_Size" },
  134.   { HIST_TYPE_OP, "Histogram_Type" },
  135.   { INITIAL_CLOCK_OP, "Initial_Clock" },
  136.   { INITIAL_FRAME_OP, "Initial_Frame" },
  137.   { INPUT_FILE_NAME_OP, "Input_File_Name" },
  138.   { JITTER_AMOUNT_OP, "Jitter_Amount" },
  139.   { JITTER_OP, "Jitter" },
  140.   { LIBRARY_PATH_OP, "Library_Path" },
  141.   { LIGHT_BUFFER_OP, "Light_Buffer" },
  142.   { ODD_FIELD_OP, "Odd_Field" },
  143.  
  144.   { OUTPUT_ALPHA_OP, "Output_Alpha" },
  145.   { OUTPUT_FILE_NAME_OP, "Output_File_Name" },
  146.   { PALETTE_OP, "Palette" },
  147.   { PAUSE_WHEN_DONE_OP, "Pause_When_Done" },
  148.   { POST_FRAME_CMD_OP, "Post_Frame_Command" },
  149.   { POST_FRAME_RET_OP, "Post_Frame_Return" },
  150.   { POST_SCENE_CMD_OP, "Post_Scene_Command" },
  151.   { POST_SCENE_RET_OP, "Post_Scene_Return" },
  152.   { PREVIEW_E_OP, "Preview_End_Size" },
  153.   { PREVIEW_S_OP, "Preview_Start_Size" },
  154.  
  155.   { PRE_FRAME_CMD_OP, "Pre_Frame_Command" },
  156.   { PRE_FRAME_RET_OP, "Pre_Frame_Return" },
  157.   { PRE_SCENE_CMD_OP, "Pre_Scene_command" },
  158.   { PRE_SCENE_RET_OP, "Pre_Scene_Return" },
  159.   { QUALITY_OP, "Quality" },
  160.   { RAD_SWITCH_OP, "Radiosity" },
  161.   { REMOVE_BOUNDS_OP, "Remove_Bounds" },
  162.   { RENDER_CONSOLE_OP, "Render_Console" },
  163.   { RENDER_FILE_OP, "Render_File" },
  164.   { SAMPLING_METHOD_OP, "Sampling_Method" },
  165.  
  166.   { SPLIT_UNIONS_OP, "Split_Unions" },
  167.   { START_COLUMN_OP, "Start_Column" },
  168.   { START_ROW_OP, "Start_Row" },
  169.   { STATISTIC_CONSOLE_OP, "Statistic_Console" },
  170.   { STATISTIC_FILE_OP, "Statistic_File" },
  171.   { SUBSET_END_FRAME_OP, "Subset_End_Frame" },
  172.   { SUBSET_START_FRAME_OP, "Subset_Start_Frame" },
  173.   { TEST_ABORT_COUNT_OP, "Test_Abort_Count" },
  174.   { TEST_ABORT_OP, "Test_Abort" },
  175.   { USER_ABORT_CMD_OP, "User_Abort_Command" },
  176.  
  177.   { USER_ABORT_RET_OP, "User_Abort_Return" },
  178.   { VERBOSE_OP, "Verbose" },
  179.   { VERSION_OP, "Version" },
  180.   { VIDEO_MODE_OP, "Video_Mode" },
  181.   { VISTA_BUFFER_OP, "Vista_Buffer" },
  182.   { WARNING_CONSOLE_OP, "Warning_Console" },
  183.   { WARNING_FILE_OP, "Warning_File" },
  184.   { WIDTH_OP, "Width" },
  185.  
  186.   { BITS_PER_COLOR_OP, "Bits_Per_Color" },
  187.   { BITS_PER_COLOUR_OP, "Bits_Per_Colour" },
  188.   { INCLUDE_INI_OP, "Include_Ini" }
  189. };
  190.  
  191. static char temp_string[3]="\0\0";
  192. static char ret_string[7]="IQUFSA";
  193.  
  194. /*****************************************************************************
  195. * static functions
  196. ******************************************************************************/
  197.  
  198. static int matches PARAMS(( char *v1, char *v2 ));
  199. static int istrue PARAMS(( char *value ));
  200. static int isfalse PARAMS(( char *value ));
  201.  
  202. /*****************************************************************************
  203. *
  204. * FUNCTION
  205. *
  206. *   get_ini_value
  207. *
  208. * INPUT
  209. *
  210. *   op - the .ini option's index
  211. *   libind - if op = LIBRARY_PATH_OP, the library's index
  212. *   
  213. * OUTPUT
  214. *   
  215. * RETURNS
  216. *
  217. *   char * pointing to a static string representation of the
  218. *   option's value.
  219. *   
  220. * AUTHOR
  221. *
  222. *   SCD, 2/95
  223. *   
  224. * DESCRIPTION
  225. *
  226. *   Returns a static string representation of an option's value.
  227. *
  228. * CHANGES
  229. *
  230. *   -
  231. *
  232. ******************************************************************************/
  233.  
  234. char *get_ini_value(op, libind)
  235. int op, libind;
  236. {
  237.   static char value[128];
  238.  
  239.   value[0] = '\0';
  240.  
  241.   switch (op)
  242.   {
  243.     case BUF_SIZE_OP:
  244.       sprintf(value,"%d", opts.File_Buffer_Size>>10);
  245.       return(value);
  246.  
  247.     case BUFFERED_OUTPUT_OP:
  248.       return (opts.Options & BUFFERED_OUTPUT ? "On" : "Off");
  249.  
  250.     case CONTINUE_OP:
  251.       return (opts.Options & CONTINUE_TRACE ? "On" : "Off");
  252.  
  253.     case DISPLAY_OP:
  254.       return (opts.Options & DISPLAY ? "On" : "Off");
  255.  
  256.     case VIDEO_MODE_OP:
  257.       sprintf(value,"%c",opts.DisplayFormat);
  258.       return(value);
  259.  
  260.     case PALETTE_OP:
  261.       sprintf(value,"%c",opts.PaletteOption);
  262.       return(value);
  263.  
  264.     case VERBOSE_OP:
  265.       return (opts.Options & VERBOSE ? "On" : "Off");
  266.  
  267.     case WIDTH_OP:
  268.       sprintf(value,"%d",Frame.Screen_Width);
  269.       return(value);
  270.  
  271.     case HEIGHT_OP:
  272.       sprintf(value,"%d",Frame.Screen_Height);
  273.       return(value);
  274.  
  275.     case FILE_OUTPUT_OP:
  276.       return (opts.Options & DISKWRITE ? "On" : "Off");
  277.  
  278.     case FILE_OUTPUT_TYPE_OP:
  279.       sprintf(value,"%c",opts.OutputFormat);
  280.       return(value);
  281.  
  282.     case PAUSE_WHEN_DONE_OP:
  283.       return (opts.Options & PROMPTEXIT ? "On" : "Off");
  284.  
  285.     case INPUT_FILE_NAME_OP:
  286.       return opts.Input_File_Name;
  287.  
  288.     case OUTPUT_FILE_NAME_OP:
  289.       return opts.Output_File_Name;
  290.  
  291.     case ANTIALIAS_OP:
  292.       return (opts.Options & ANTIALIAS ? "On" : "Off");
  293.  
  294.     case ANTIALIAS_THRESH_OP:
  295.       sprintf(value,"%g",opts.Antialias_Threshold);
  296.       return(value);
  297.  
  298.     case ANTIALIAS_DEPTH_OP:
  299.       sprintf(value,"%ld",opts.AntialiasDepth);
  300.       return(value);
  301.  
  302.     case JITTER_OP:
  303.       return (opts.Options & JITTER ? "On" : "Off");
  304.  
  305.     case JITTER_AMOUNT_OP:
  306.       sprintf(value,"%g",opts.JitterScale);
  307.       return(value);
  308.  
  309.     case TEST_ABORT_OP:
  310.       return (opts.Options & EXITENABLE ? "On" : "Off");
  311.  
  312.     case TEST_ABORT_COUNT_OP:
  313.       sprintf(value,"%d",opts.Abort_Test_Counter);
  314.       return(value);
  315.  
  316.     case LIBRARY_PATH_OP:
  317.       return opts.Library_Paths[libind];
  318.  
  319.     case START_COLUMN_OP:
  320.       if (opts.First_Column == -1)
  321.         sprintf(value,"%g",opts.First_Column_Percent);
  322.       else
  323.         sprintf(value,"%d",opts.First_Column);
  324.       return(value);
  325.  
  326.     case START_ROW_OP:
  327.       if (opts.First_Line == -1)
  328.         sprintf(value,"%g",opts.First_Line_Percent);
  329.       else
  330.         sprintf(value,"%d",opts.First_Line);
  331.       return(value);
  332.  
  333.     case END_COLUMN_OP:
  334.       if (opts.Last_Column == -1)
  335.         sprintf(value,"%g",opts.Last_Column_Percent);
  336.       else
  337.         sprintf(value,"%d",opts.Last_Column);
  338.       return(value);
  339.  
  340.     case END_ROW_OP:
  341.       if (opts.Last_Line == -1)
  342.         sprintf(value,"%g",opts.Last_Line_Percent);
  343.       else
  344.         sprintf(value,"%d",opts.Last_Line);
  345.       return(value);
  346.  
  347.     case VERSION_OP:
  348.       sprintf(value,"%g",opts.Language_Version);
  349.       return(value);
  350.  
  351.     case BOUNDING_OP:
  352.       return (opts.Use_Slabs ? "On" : "Off");
  353.  
  354.     case BOUNDING_THRESH_OP:
  355.       sprintf(value,"%ld",opts.BBox_Threshold);
  356.       return(value);
  357.  
  358.     case QUALITY_OP:
  359.       sprintf(value,"%d",opts.Quality);
  360.       return(value);
  361.  
  362.     case PREVIEW_S_OP:
  363.       sprintf(value,"%d",opts.PreviewGridSize_Start);
  364.       return value;
  365.  
  366.     case PREVIEW_E_OP:
  367.       sprintf(value,"%d",opts.PreviewGridSize_End);
  368.       return value;
  369.  
  370.     case CLOCK_OP:
  371.       sprintf(value,"%g",opts.FrameSeq.Clock_Value);
  372.       return value;
  373.  
  374.     case INITIAL_FRAME_OP:
  375.       sprintf(value,"%d",opts.FrameSeq.InitialFrame);
  376.       return value;
  377.  
  378.     case INITIAL_CLOCK_OP:
  379.       sprintf(value,"%g",opts.FrameSeq.InitialClock);
  380.       return value;
  381.  
  382.     case FINAL_FRAME_OP:
  383.       sprintf(value,"%d",opts.FrameSeq.FinalFrame);
  384.       return value;
  385.  
  386.     case FINAL_CLOCK_OP:
  387.       sprintf(value,"%g",opts.FrameSeq.FinalClock);
  388.       return value;
  389.  
  390.     case SUBSET_START_FRAME_OP:
  391.       sprintf(value,"%d",opts.FrameSeq.SubsetStartFrame);
  392.       return value;
  393.  
  394.     case SUBSET_END_FRAME_OP:
  395.       sprintf(value,"%d",opts.FrameSeq.SubsetEndFrame);
  396.       return value;
  397.  
  398.     case CREATE_INI_OP:
  399.       return opts.Ini_Output_File_Name;
  400.  
  401.     case ALL_CONSOLE_OP:
  402.       return (Stream_Info[ALL_STREAM].do_console ? "On" : "Off");
  403.  
  404.     case ALL_FILE_OP:
  405.       return (Stream_Info[ALL_STREAM].name ? Stream_Info[ALL_STREAM].name : "");
  406.  
  407.     case DEBUG_CONSOLE_OP:
  408.       return (Stream_Info[DEBUG_STREAM].do_console ? "On" : "Off");
  409.  
  410.     case DEBUG_FILE_OP:
  411.       return (Stream_Info[DEBUG_STREAM].name ? Stream_Info[DEBUG_STREAM].name : "");
  412.  
  413.     case RENDER_CONSOLE_OP:
  414.       return (Stream_Info[RENDER_STREAM].do_console ? "On" : "Off");
  415.  
  416.     case RENDER_FILE_OP:
  417.       return (Stream_Info[RENDER_STREAM].name ? Stream_Info[RENDER_STREAM].name : "");
  418.  
  419.     case STATISTIC_CONSOLE_OP:
  420.       return (Stream_Info[STATISTIC_STREAM].do_console ? "On" : "Off");
  421.  
  422.     case STATISTIC_FILE_OP:
  423.       return (Stream_Info[STATISTIC_STREAM].name ? Stream_Info[STATISTIC_STREAM].name : "");
  424.  
  425.     case WARNING_CONSOLE_OP:
  426.       return (Stream_Info[WARNING_STREAM].do_console ? "On" : "Off");
  427.  
  428.     case WARNING_FILE_OP:
  429.       return (Stream_Info[WARNING_STREAM].name ? Stream_Info[WARNING_STREAM].name : "");
  430.  
  431.     case FATAL_CONSOLE_OP:
  432.       return (Stream_Info[FATAL_STREAM].do_console ? "On" : "Off");
  433.  
  434.     case FATAL_FILE_OP:
  435.       return (Stream_Info[FATAL_STREAM].name ? Stream_Info[FATAL_STREAM].name : "");
  436.  
  437.     case RAD_SWITCH_OP:
  438.       return (opts.Options & RADIOSITY ? "On" : "Off");
  439.  
  440.     case HIST_SIZE_OP:
  441.       sprintf (value, "%d.%d", opts.histogram_x, opts.histogram_y) ;
  442.       return (value) ;
  443.  
  444.     case HIST_TYPE_OP:
  445.       switch (opts.histogram_type)
  446.       {
  447.         case CSV :
  448.           return ("C ; CSV") ;
  449.  
  450.         case SYS :
  451.           return ("S ; SYS") ;
  452.  
  453.         case PPM :
  454.           return ("P ; PPM") ;
  455.  
  456.         case TARGA :
  457.           return ("T ; TARGA") ;
  458.  
  459.         case PNG :
  460.           return ("N ; PNG") ;
  461.  
  462.         case NONE :
  463.           return ("X ; NONE") ;
  464.  
  465.       }
  466.       return ("X ; [UNKNOWN VALUE PASSED]") ;
  467.  
  468.     case HIST_NAME_OP:
  469.       return (opts.Histogram_File_Name) ;
  470.  
  471.     case VISTA_BUFFER_OP:
  472.       return ((opts.Options & USE_VISTA_BUFFER) ? "On" : "Off");
  473.  
  474.     case LIGHT_BUFFER_OP:
  475.       return ((opts.Options & USE_LIGHT_BUFFER) ? "On" : "Off");
  476.  
  477.     case DRAW_VISTAS_OP:
  478.       return ((opts.Options & USE_VISTA_DRAW) ? "On" : "Off");
  479.  
  480.     case SPLIT_UNIONS_OP:
  481.       return ((opts.Options & SPLIT_UNION) ? "On" : "Off");
  482.  
  483.     case REMOVE_BOUNDS_OP:
  484.       return ((opts.Options & REMOVE_BOUNDS) ? "On" : "Off");
  485.  
  486.     case CYCLIC_ANIMATION_OP:
  487.       return ((opts.Options & CYCLIC_ANIMATION) ? "On" : "Off");
  488.  
  489.     case PRE_SCENE_CMD_OP:
  490.       return opts.Shellouts[PRE_SCENE_SHL].Command;
  491.  
  492.     case PRE_FRAME_CMD_OP:
  493.       return opts.Shellouts[PRE_FRAME_SHL].Command;
  494.  
  495.     case POST_FRAME_CMD_OP:
  496.       return opts.Shellouts[POST_FRAME_SHL].Command;
  497.  
  498.     case POST_SCENE_CMD_OP:
  499.       return opts.Shellouts[POST_SCENE_SHL].Command;
  500.  
  501.     case USER_ABORT_CMD_OP:
  502.       return opts.Shellouts[USER_ABORT_SHL].Command;
  503.  
  504.     case FATAL_ERROR_CMD_OP:
  505.       return opts.Shellouts[FATAL_SHL].Command;
  506.  
  507.     case PRE_SCENE_RET_OP:
  508.       temp_string[0]=(opts.Shellouts[PRE_SCENE_SHL].Inverse)?'!':' ';
  509.       temp_string[1]=ret_string[opts.Shellouts[PRE_SCENE_SHL].Ret];
  510.       return temp_string;
  511.  
  512.     case PRE_FRAME_RET_OP:
  513.       temp_string[0]=(opts.Shellouts[PRE_FRAME_SHL].Inverse)?'!':' ';
  514.       temp_string[1]=ret_string[opts.Shellouts[PRE_FRAME_SHL].Ret];
  515.       return temp_string;
  516.  
  517.     case POST_FRAME_RET_OP:
  518.       temp_string[0]=(opts.Shellouts[POST_FRAME_SHL].Inverse)?'!':' ';
  519.       temp_string[1]=ret_string[opts.Shellouts[POST_FRAME_SHL].Ret];
  520.       return temp_string;
  521.  
  522.     case POST_SCENE_RET_OP:
  523.       temp_string[0]=(opts.Shellouts[POST_SCENE_SHL].Inverse)?'!':' ';
  524.       temp_string[1]=ret_string[opts.Shellouts[POST_SCENE_SHL].Ret];
  525.       return temp_string;
  526.  
  527.     case USER_ABORT_RET_OP:
  528.       temp_string[0]=(opts.Shellouts[USER_ABORT_SHL].Inverse)?'!':' ';
  529.       temp_string[1]=ret_string[opts.Shellouts[USER_ABORT_SHL].Ret];
  530.       return temp_string;
  531.  
  532.     case FATAL_ERROR_RET_OP:
  533.       temp_string[0]=(opts.Shellouts[FATAL_SHL].Inverse)?'!':' ';
  534.       temp_string[1]=ret_string[opts.Shellouts[FATAL_SHL].Ret];
  535.       return temp_string;
  536.  
  537.     case OUTPUT_ALPHA_OP:
  538.       return ((opts.Options & OUTPUT_ALPHA) ? "On" : "Off");
  539.  
  540.     case FIELD_RENDER_OP:
  541.       return (opts.FrameSeq.Field_Render_Flag ? "On" : "Off");
  542.  
  543.     case ODD_FIELD_OP:
  544.       return (opts.FrameSeq.Odd_Field_Flag ? "On" : "Off");
  545.       
  546.     case SAMPLING_METHOD_OP:
  547.       sprintf(value,"%d",opts.Tracing_Method);
  548.       return value;
  549.  
  550.     case BITS_PER_COLOR_OP:
  551.     case BITS_PER_COLOUR_OP:
  552.       sprintf(value,"%d",opts.OutputQuality);
  553.       return value;
  554.  
  555.     case DISPLAY_GAMMA_OP:
  556.       sprintf(value,"%g",opts.DisplayGamma);
  557.       return value;
  558.  
  559.     case INCLUDE_INI_OP:
  560.       value[0] = '\0';
  561.       return value;
  562.  
  563.     default:
  564.       Error("Unknown INI option in Write_INI.");
  565.   }
  566.  
  567.   return(value);
  568. }
  569.  
  570.  
  571.  
  572. /*****************************************************************************
  573. *
  574. * FUNCTION
  575. *
  576. *   parse_switch
  577. *
  578. * INPUT
  579. *   
  580. * OUTPUT
  581. *   
  582. * RETURNS
  583. *   
  584. * AUTHOR
  585. *
  586. *   POV-Ray Team
  587. *   
  588. * DESCRIPTION
  589. *
  590. *   Parses a traditional POV-Ray command-line switch that starts
  591. *   with + or -.  Whenever it seemed feasible, calls process_variable
  592. *   to perform the function rather than doing so itself.  Although this
  593. *   requires another pass through a switch{case, case...}, it insures
  594. *   that command-line switches and variable=value options get treated
  595. *   identically.
  596. *
  597. * CHANGES
  598. *
  599. *   -
  600. *
  601. *   Sep 1994 : Added options for union splitting, vista/light buffer. [DB]
  602. *   Jan 1995 : Added options for histogram grid. [CJC]
  603. *   Feb 1995 : Added options for console/file redirection and .INI writing [SCD]
  604. *
  605. ******************************************************************************/
  606.  
  607. void parse_switch (Option_String)
  608. char *Option_String;
  609. {
  610.   int i;
  611.   unsigned long Add_Option;
  612.   unsigned long Option_Number;
  613.   long longval;
  614.   DBL floatval;
  615.  
  616.   /* If these flags aren't immediately used, reset them on next -/+ option! */
  617.  
  618.   inflag = outflag = FALSE;
  619.  
  620.   if (*(Option_String++) == '-')
  621.   {
  622.     Add_Option = FALSE;
  623.   }
  624.   else
  625.   {
  626.     Add_Option = TRUE;
  627.   }
  628.  
  629.   Option_Number = 0;
  630.  
  631.   switch (*Option_String)
  632.   {
  633.     case '?':
  634.  
  635.       if (Option_String[1] == '\0')
  636.       {
  637.         Usage(0, TRUE);
  638.       }
  639.       else
  640.       {
  641.         sscanf (&Option_String[1], "%d", &i);
  642.  
  643.         if ((i >= 0) && (i <= MAX_HELP_PAGE))
  644.         {
  645.           Usage(i, TRUE);
  646.         }
  647.         else
  648.         {
  649.           Usage(0, TRUE);
  650.         }
  651.       }
  652.  
  653.       break;
  654.  
  655.     case '@':
  656.  
  657.       Warning(0.0,"The +@ switch no longer supported. Use +GS.\n");
  658.  
  659.       break;
  660.  
  661.     case 'A':
  662.     case 'a':
  663.  
  664.       switch (Option_String[1])
  665.       {
  666.         case 'm':
  667.         case 'M':
  668.  
  669.           switch (Option_String[2])
  670.           {
  671.             case '1':
  672.  
  673.               opts.Tracing_Method = 1;
  674.  
  675.               break;
  676.  
  677.             case '2':
  678.  
  679.               opts.Tracing_Method = 2;
  680.  
  681.               break;
  682.  
  683.             default:
  684.  
  685.               Warning(0.0, "Unknown antialiasing method. Standard method used.\n");
  686.  
  687.               opts.Tracing_Method = 1;
  688.           }
  689.  
  690.           break;
  691.  
  692.         default:
  693.  
  694.           Option_Number = ANTIALIAS;
  695.  
  696.           if (sscanf (&Option_String[1], DBL_FORMAT_STRING, &floatval) != EOF)
  697.           {
  698.             opts.Antialias_Threshold = floatval;
  699.           }
  700.       }
  701.  
  702.       break;
  703.  
  704.     case 'B':
  705.     case 'b':
  706.  
  707.       Option_Number = BUFFERED_OUTPUT;
  708.  
  709.       if (sscanf (&Option_String[1], "%d", &opts.File_Buffer_Size) != EOF)
  710.       {
  711.         opts.File_Buffer_Size *= 1024;
  712.  
  713.         if (opts.File_Buffer_Size > MAX_BUFSIZE)
  714.         {
  715.           opts.File_Buffer_Size = MAX_BUFSIZE;
  716.         }
  717.         /* If 0 then no buffer, other low values use system default MIN */
  718.  
  719.         if ((opts.File_Buffer_Size > 0) && (opts.File_Buffer_Size < BUFSIZ))
  720.         {
  721.           opts.File_Buffer_Size = BUFSIZ;
  722.         }
  723.  
  724.         if (opts.File_Buffer_Size <= 0)
  725.         {
  726.           Add_Option = FALSE;
  727.         }
  728.       }
  729.  
  730.       break;
  731.  
  732.     case 'C':
  733.     case 'c':
  734.  
  735.       Option_Number = CONTINUE_TRACE;
  736.  
  737.       break;
  738.  
  739.     case 'D':
  740.     case 'd':
  741.  
  742.       Option_Number = DISPLAY;
  743.  
  744.       if (Option_String[1] != '\0')
  745.       {
  746.         opts.DisplayFormat = (char)toupper(Option_String[1]);
  747.       }
  748.  
  749.       if (Option_String[1] != '\0' && Option_String[2] != '\0')
  750.       {
  751.         opts.PaletteOption = (char)toupper(Option_String[2]);
  752.       }
  753.  
  754.       break;
  755.  
  756.     case 'E':
  757.     case 'e':
  758.  
  759.       switch (Option_String[1])
  760.       {
  761.         case 'c':
  762.         case 'C':
  763.  
  764.           process_variable(END_COLUMN_OP,&Option_String[2]);
  765.  
  766.           break;
  767.  
  768.         case 'f':
  769.         case 'F':
  770.           if(isdigit(Option_String[2]))
  771.             process_variable(SUBSET_END_FRAME_OP, &Option_String[2]);
  772.           break;
  773.  
  774.         case 'r':
  775.         case 'R':
  776.  
  777.           process_variable(END_ROW_OP,&Option_String[2]);
  778.  
  779.           break;
  780.  
  781.         case 'p': /* Mosaic Preview Grid Size - End */
  782.         case 'P':
  783.  
  784.           process_variable(PREVIEW_E_OP,&Option_String[2]);
  785.  
  786.           break;
  787.  
  788.         default:
  789.  
  790.           process_variable(END_ROW_OP,&Option_String[1]);
  791.       }
  792.  
  793.       break;
  794.  
  795.     case 'F':
  796.     case 'f':
  797.  
  798.       Option_Number = DISKWRITE;
  799.       
  800.       if (Option_String[1] != '\0')
  801.       {
  802.         opts.OutputFormat = (char)tolower(Option_String[1]);
  803.       }
  804.  
  805.       if (sscanf(&Option_String[2], "%d", &opts.OutputQuality) != 1)
  806.       {
  807.         opts.OutputQuality = 8;
  808.       }
  809.  
  810.       break;
  811.  
  812.     /* Console/file redirection, .INI dump option - [SCD 2/95] */
  813.  
  814.     case 'G':
  815.     case 'g':
  816.  
  817.       switch (Option_String[1])
  818.       {
  819.         case 'a':  /* All */
  820.         case 'A':
  821.  
  822.           process_variable(ALL_CONSOLE_OP,Add_Option ? "On" : "Off");
  823.           process_variable(ALL_FILE_OP,&Option_String[2]);
  824.  
  825.           break;
  826.  
  827.         case 'd':  /* DebugInfo */
  828.         case 'D':
  829.  
  830.           process_variable(DEBUG_CONSOLE_OP,Add_Option ? "On" : "Off");
  831.           process_variable(DEBUG_FILE_OP,&Option_String[2]);
  832.  
  833.           break;
  834.  
  835.         case 'f':  /* Fatal */
  836.         case 'F':
  837.  
  838.           process_variable(FATAL_CONSOLE_OP,Add_Option ? "On" : "Off");
  839.           process_variable(FATAL_FILE_OP,&Option_String[2]);
  840.  
  841.           break;
  842.  
  843.         case 'i':  /* Create .INI containing all settings */
  844.         case 'I':
  845.  
  846.           process_variable(CREATE_INI_OP,&Option_String[2]);
  847.  
  848.           break;
  849.  
  850.         case 'r':  /* RenderInfo */
  851.         case 'R':
  852.  
  853.           process_variable(RENDER_CONSOLE_OP,Add_Option ? "On" : "Off");
  854.           process_variable(RENDER_FILE_OP,&Option_String[2]);
  855.  
  856.           break;
  857.  
  858.         case 's':  /* Statistics */
  859.         case 'S':
  860.  
  861.           process_variable(STATISTIC_CONSOLE_OP,Add_Option ? "On" : "Off");
  862.           process_variable(STATISTIC_FILE_OP,&Option_String[2]);
  863.  
  864.           break;
  865.  
  866.         case 'w':  /* Warning */
  867.         case 'W':
  868.  
  869.           process_variable(WARNING_CONSOLE_OP,Add_Option ? "On" : "Off");
  870.           process_variable(WARNING_FILE_OP,&Option_String[2]);
  871.  
  872.           break;
  873.  
  874.       }
  875.  
  876.       break;
  877.  
  878.     case 'H':
  879.     case 'h':
  880.  
  881.       if (Help_Available)
  882.       {
  883.         if (Option_String[1] == '\0')
  884.         {
  885.           Usage(0, TRUE);
  886.         }
  887.         else
  888.         {
  889.           sscanf (&Option_String[1], "%d", &Frame.Screen_Height);
  890.  
  891.           if ((Frame.Screen_Height >= 0) &&  (Frame.Screen_Height <= MAX_HELP_PAGE))
  892.           {
  893.             Usage(Frame.Screen_Height, TRUE);
  894.           }
  895.         }
  896.       }
  897.       else
  898.       {
  899.         if (!isdigit (Option_String [1]))
  900.         {
  901.           switch (Option_String [1])
  902.           {
  903.             case 'n':  /* Histogram name */
  904.             case 'N':
  905.                  process_variable(HIST_NAME_OP,&Option_String[2]);
  906.                  break ;
  907.  
  908.             case 's':  /* Histogram size */
  909.             case 'S':
  910.                  process_variable(HIST_SIZE_OP,&Option_String[2]);
  911.                  break ;
  912.  
  913.             case 't':  /* Histogram type */
  914.             case 'T':
  915.                  process_variable(HIST_TYPE_OP,&Option_String[2]);
  916.                  break ;
  917.           }
  918.         }
  919.         else
  920.         {
  921.           sscanf (&Option_String[1], "%d", &Frame.Screen_Height);
  922.         }
  923.       }
  924.       break;
  925.  
  926.     case 'I':
  927.     case 'i':
  928.  
  929.       if (Option_String[1] == '\0')
  930.       {
  931.         inflag = TRUE;
  932.       }
  933.       else
  934.       {
  935.         strncpy (opts.Input_File_Name, &Option_String[1], FILE_NAME_LENGTH);
  936.       }
  937.  
  938.       break;
  939.  
  940.     case 'J':
  941.     case 'j':
  942.  
  943.       Option_Number = JITTER;
  944.  
  945.       if (sscanf (&Option_String[1], DBL_FORMAT_STRING, &floatval) != EOF)
  946.       {
  947.         opts.JitterScale = floatval;
  948.       }
  949.  
  950.       if (opts.JitterScale <= 0.0)
  951.       {
  952.         Add_Option = FALSE;
  953.       }
  954.  
  955.       break;
  956.  
  957.     case 'K':
  958.     case 'k':
  959.  
  960.       /* Animation-type clock specification */
  961.       switch(Option_String[1])
  962.       {
  963.         case 'c':
  964.         case 'C':
  965.           Option_Number = CYCLIC_ANIMATION;
  966.           break;
  967.  
  968.         case 'i':
  969.         case 'I':
  970.           process_variable(INITIAL_CLOCK_OP, &Option_String[2]);
  971.           break;
  972.  
  973.         case 'f':
  974.         case 'F':
  975.           /* Animation-type clock specification */
  976.           switch(Option_String[2])
  977.           {
  978.             case 'i':
  979.             case 'I':
  980.               process_variable(INITIAL_FRAME_OP, &Option_String[3]);
  981.               break;
  982.  
  983.             case 'f':
  984.             case 'F':
  985.               process_variable(FINAL_FRAME_OP, &Option_String[3]);
  986.               break;
  987.                
  988.             default:
  989.               process_variable(FINAL_CLOCK_OP, &Option_String[2]);
  990.               break;
  991.  
  992.           }
  993.           break;
  994.  
  995.         default:
  996.           /* Standard clock specification */
  997.           process_variable(CLOCK_OP,&Option_String[1]);
  998.           break;
  999.       }
  1000.       break;
  1001.  
  1002.     case 'L':
  1003.     case 'l':
  1004.  
  1005.       process_variable(LIBRARY_PATH_OP,&Option_String[1]);
  1006.  
  1007.       break;
  1008.  
  1009.     case 'M': /* Switch used so other max values can be inserted easily */
  1010.     case 'm':
  1011.  
  1012.       switch (Option_String[1])
  1013.       {
  1014.         case 's': /* Max Symbols */
  1015.         case 'S':
  1016.  
  1017.           Warning(0.0,"+MS or -MS switch no longer needed.\n");
  1018.           break;
  1019.  
  1020.         case 'v': /* Max Version */
  1021.         case 'V':
  1022.  
  1023.           sscanf (&Option_String[2], DBL_FORMAT_STRING, &opts.Language_Version);
  1024.  
  1025.           break;
  1026.  
  1027.         case 'b': /* Min Bounded */
  1028.         case 'B':
  1029.  
  1030.           if (sscanf (&Option_String[2], "%ld", &longval) != EOF)
  1031.           {
  1032.             opts.BBox_Threshold=longval;
  1033.           }
  1034.  
  1035.           opts.Use_Slabs = Add_Option;
  1036.  
  1037.           break;
  1038.  
  1039.         default:
  1040.  
  1041.           break;
  1042.       }
  1043.  
  1044.       break;
  1045.  
  1046.     case 'O':
  1047.     case 'o':
  1048.  
  1049.       if (Option_String[1] == '\0')
  1050.       {
  1051.         outflag = TRUE;
  1052.       }
  1053.       else
  1054.       {
  1055.         strncpy (opts.Output_File_Name, &Option_String[1], FILE_NAME_LENGTH);
  1056.       }
  1057.  
  1058.       break;
  1059.  
  1060.     case 'P':
  1061.     case 'p':
  1062.  
  1063.       Option_Number = PROMPTEXIT;
  1064.  
  1065.       break;
  1066.  
  1067.     case 'Q':
  1068.     case 'q':
  1069.  
  1070.       switch(Option_String[1])
  1071.       {
  1072.     case 'r':
  1073.     case 'R':
  1074.       Option_Number = RADIOSITY;
  1075.       break;
  1076.     case '0':
  1077.     case '1':
  1078.     case '2':
  1079.     case '3':
  1080.     case '4':
  1081.     case '5':
  1082.     case '6':
  1083.     case '7':
  1084.     case '8':
  1085.     case '9':
  1086.       process_variable(QUALITY_OP,&Option_String[1]);
  1087.       break;
  1088.     default:
  1089.       break;
  1090.       }
  1091.       break;
  1092.  
  1093.     case 'R':
  1094.     case 'r':
  1095.  
  1096.       process_variable(ANTIALIAS_DEPTH_OP,&Option_String[1]);
  1097.  
  1098.       break;
  1099.  
  1100.     case 'S':
  1101.     case 's':
  1102.  
  1103.       switch (Option_String[1])
  1104.       {
  1105.         case 'c':
  1106.         case 'C':
  1107.  
  1108.           process_variable(START_COLUMN_OP,&Option_String[2]);
  1109.  
  1110.           break;
  1111.  
  1112.         case 'r':
  1113.         case 'R':
  1114.  
  1115.           process_variable(START_ROW_OP,&Option_String[2]);
  1116.  
  1117.           break;
  1118.  
  1119.         case 'f':
  1120.         case 'F':
  1121.           process_variable(SUBSET_START_FRAME_OP, &Option_String[2]);
  1122.           break;
  1123.  
  1124.         case 'p': /* Mosaic Preview Grid Size - Start */
  1125.         case 'P':
  1126.  
  1127.           process_variable(PREVIEW_S_OP,&Option_String[2]);
  1128.  
  1129.           break;
  1130.  
  1131.         /* Split unions option. [DB 9/94] */
  1132.  
  1133.         case 'U':
  1134.         case 'u':
  1135.  
  1136.           Option_Number = SPLIT_UNION;
  1137.  
  1138.           break;
  1139.  
  1140.         default:
  1141.  
  1142.           process_variable(START_ROW_OP,&Option_String[1]);
  1143.       }
  1144.  
  1145.       break;
  1146.  
  1147.     /* Read vista/light buffer options. [DB 9/94] */
  1148.  
  1149.     case 'U':
  1150.     case 'u':
  1151.  
  1152.       switch (Option_String[1])
  1153.       {
  1154.         case 'l':
  1155.         case 'L':
  1156.  
  1157.           Option_Number = USE_LIGHT_BUFFER;
  1158.  
  1159.           break;
  1160.  
  1161.         case 'd':
  1162.         case 'D':
  1163.  
  1164.           Option_Number = USE_VISTA_DRAW;
  1165.  
  1166.           break;
  1167.  
  1168.         case 'r':
  1169.         case 'R':
  1170.  
  1171.            Option_Number = REMOVE_BOUNDS;
  1172.  
  1173.            break;
  1174.  
  1175.         case 'v':
  1176.         case 'V':
  1177.  
  1178.           Option_Number = USE_VISTA_BUFFER;
  1179.  
  1180.           break;
  1181.  
  1182.         case 'a':
  1183.         case 'A':
  1184.  
  1185.           Option_Number = OUTPUT_ALPHA;
  1186.  
  1187.           break;
  1188.  
  1189.         case 'f':
  1190.         case 'F':
  1191.  
  1192.           process_variable(FIELD_RENDER_OP, Add_Option ? "True" : "False");
  1193.  
  1194.           break;
  1195.  
  1196.         case 'o':
  1197.         case 'O':
  1198.  
  1199.           process_variable(ODD_FIELD_OP, Add_Option ? "True" : "False");
  1200.  
  1201.           break;
  1202.       }
  1203.  
  1204.       break;
  1205.  
  1206.     case 'V':
  1207.     case 'v':
  1208.  
  1209.       Option_Number = VERBOSE;
  1210.       break;
  1211.  
  1212.     case 'W':
  1213.     case 'w':
  1214.  
  1215.       sscanf (&Option_String[1], "%d", &Frame.Screen_Width);
  1216.  
  1217.       break;
  1218.  
  1219.     case 'X':
  1220.     case 'x':
  1221.  
  1222.       Option_Number = EXITENABLE;
  1223.  
  1224.       sscanf (&Option_String[1], "%d", &Abort_Test_Every);
  1225.  
  1226.       opts.Abort_Test_Counter = Abort_Test_Every;
  1227.  
  1228.       break;
  1229.  
  1230.     default:
  1231.  
  1232.       Warning (0.0,"Invalid option: %s.\n", --Option_String);
  1233.   }
  1234.  
  1235.   if (Option_Number != 0)
  1236.   {
  1237.     if (Add_Option)
  1238.     {
  1239.       opts.Options |= Option_Number;
  1240.     }
  1241.     else
  1242.     {
  1243.       opts.Options &= ~Option_Number;
  1244.     }
  1245.   }
  1246. }
  1247.  
  1248.  
  1249.  
  1250.  
  1251. /*****************************************************************************
  1252. *
  1253. * FUNCTION
  1254. *
  1255. *   process_variable
  1256. *
  1257. * INPUT
  1258. *
  1259. * OUTPUT
  1260. *   
  1261. * RETURNS
  1262. *   
  1263. * AUTHOR
  1264. *
  1265. *   POV-Ray Team
  1266. *   
  1267. * DESCRIPTION
  1268. *
  1269. *   Given a token number representing an option variable and a string
  1270. *   that is the value to set, set one option.  If its just an on/off
  1271. *   switch that takes a boolean value then just set Option_Number and
  1272. *   break.  Otherwise process the value and return. 
  1273. *
  1274. * CHANGES
  1275. *
  1276. *   -
  1277. *
  1278. ******************************************************************************/
  1279.  
  1280. void process_variable(variable,value)
  1281. TOKEN variable;
  1282. char *value;
  1283. {
  1284.   int i;
  1285.   long longval;
  1286.   unsigned int Option_Number = 0;
  1287.   DBL floatval;
  1288.  
  1289.   switch (variable)
  1290.   {
  1291.     case BUF_SIZE_OP:
  1292.       opts.File_Buffer_Size = atoi(value)*1024;
  1293.       if (opts.File_Buffer_Size > MAX_BUFSIZE)
  1294.         opts.File_Buffer_Size = MAX_BUFSIZE;
  1295.       /* If 0 then no buffer, other low values use system default MIN */
  1296.       if ((opts.File_Buffer_Size > 0) && (opts.File_Buffer_Size < BUFSIZ))
  1297.       {
  1298.         opts.File_Buffer_Size = BUFSIZ;
  1299.       }
  1300.       if (opts.File_Buffer_Size <= 0)
  1301.       {
  1302.         opts.Options &= ~BUFFERED_OUTPUT;
  1303.       }
  1304.       return;
  1305.  
  1306.     case BUFFERED_OUTPUT_OP:
  1307.       Option_Number = BUFFERED_OUTPUT;
  1308.       break;
  1309.  
  1310.     case CONTINUE_OP:
  1311.       Option_Number = CONTINUE_TRACE;
  1312.       break;
  1313.  
  1314.     case DISPLAY_OP:
  1315.       Option_Number = DISPLAY;
  1316.       break;
  1317.  
  1318.     case VIDEO_MODE_OP:
  1319.       opts.DisplayFormat = (char)toupper(value[0]);
  1320.       return;
  1321.  
  1322.     case PALETTE_OP:
  1323.       opts.PaletteOption = (char)toupper(value[0]);
  1324.       return;
  1325.  
  1326.     case VERBOSE_OP:
  1327.       Option_Number = VERBOSE;
  1328.       break;
  1329.  
  1330.     case WIDTH_OP:
  1331.       Frame.Screen_Width = atoi(value);
  1332.       return;
  1333.  
  1334.     case HEIGHT_OP:
  1335.       Frame.Screen_Height = atoi(value);
  1336.       return;
  1337.  
  1338.     case FILE_OUTPUT_OP:
  1339.       Option_Number = DISKWRITE;
  1340.       break;
  1341.  
  1342.     case FILE_OUTPUT_TYPE_OP:
  1343.       opts.OutputFormat = (char)tolower(value[0]);
  1344.       return;
  1345.  
  1346.     case PAUSE_WHEN_DONE_OP:
  1347.       Option_Number = PROMPTEXIT;
  1348.       break;
  1349.  
  1350.     case INPUT_FILE_NAME_OP:
  1351.       strncpy (opts.Input_File_Name, value, FILE_NAME_LENGTH);
  1352.       return;
  1353.  
  1354.     case OUTPUT_FILE_NAME_OP:
  1355.       strncpy (opts.Output_File_Name, value, FILE_NAME_LENGTH);
  1356.       return;
  1357.  
  1358.     case ANTIALIAS_OP:
  1359.       Option_Number = ANTIALIAS;
  1360.       break;
  1361.  
  1362.     case ANTIALIAS_THRESH_OP:
  1363.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != EOF)
  1364.         opts.Antialias_Threshold = floatval;
  1365.       return;
  1366.  
  1367.     case ANTIALIAS_DEPTH_OP:
  1368.       if (sscanf (value, "%ld", &longval) != EOF)
  1369.         opts.AntialiasDepth = longval;
  1370.       if (opts.AntialiasDepth < 1)
  1371.         opts.AntialiasDepth = 1;
  1372.       if (opts.AntialiasDepth > 9)
  1373.         opts.AntialiasDepth = 9;
  1374.       return;
  1375.  
  1376.     case JITTER_OP:
  1377.       Option_Number = JITTER;
  1378.       break;
  1379.  
  1380.     case JITTER_AMOUNT_OP:
  1381.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != EOF)
  1382.         opts.JitterScale = floatval;
  1383.       if (opts.JitterScale<=0.0)
  1384.         opts.Options &= ~JITTER;
  1385.       return;
  1386.  
  1387.     case TEST_ABORT_OP:
  1388.       Option_Number = EXITENABLE;
  1389.       break;
  1390.  
  1391.     case TEST_ABORT_COUNT_OP:
  1392.       sscanf (value, "%d", &Abort_Test_Every);
  1393.       opts.Abort_Test_Counter = Abort_Test_Every;
  1394.       break;
  1395.  
  1396.     case LIBRARY_PATH_OP:
  1397.       if (opts.Library_Path_Index >= MAX_LIBRARIES)
  1398.         Error ("Too many library directories specified.");
  1399.       for (i = 0; i < opts.Library_Path_Index; i++)
  1400.         if (strcmp(value,opts.Library_Paths[i])==0) return;
  1401.       opts.Library_Paths[opts.Library_Path_Index] = POV_MALLOC(strlen(value)+1,
  1402.                  "library paths");
  1403.       strcpy (opts.Library_Paths [opts.Library_Path_Index], value);
  1404.       opts.Library_Path_Index++;
  1405.       return;
  1406.  
  1407.     case START_COLUMN_OP:
  1408.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != EOF)
  1409.         if(floatval > 0.0 && floatval < 1.0)
  1410.         {
  1411.           opts.First_Column = -1;
  1412.           opts.First_Column_Percent = floatval;
  1413.         }
  1414.         else
  1415.           opts.First_Column = ((int) floatval);
  1416.           /* The above used to have -1 but it messed up Write_INI_File.
  1417.            * Moved -1 fudge to fix_up_rendering_window 
  1418.            */
  1419.       return;
  1420.  
  1421.     case START_ROW_OP:
  1422.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != EOF)
  1423.         if(floatval > 0.0 && floatval < 1.0)
  1424.         {
  1425.           opts.First_Line = -1;
  1426.           opts.First_Line_Percent = floatval;
  1427.         }
  1428.         else
  1429.           opts.First_Line = ((int) floatval);
  1430.           /* The above used to have -1 but it messed up Write_INI_File
  1431.           * Moved -1 fudge to fix_up_rendering_window 
  1432.           */
  1433.       return;
  1434.  
  1435.     case END_COLUMN_OP:
  1436.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != EOF)
  1437.         if(floatval > 0.0 && floatval <= 1.0)
  1438.         {
  1439.           opts.Last_Column = -1;
  1440.           opts.Last_Column_Percent = floatval;
  1441.         }
  1442.         else
  1443.           opts.Last_Column = (int) floatval;
  1444.       return;
  1445.  
  1446.     case END_ROW_OP:
  1447.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != EOF)
  1448.         if(floatval > 0.0 && floatval <= 1.0)
  1449.         {
  1450.           opts.Last_Line = -1;
  1451.           opts.Last_Line_Percent = floatval;
  1452.         }
  1453.         else
  1454.           opts.Last_Line = (int) floatval;
  1455.       return;
  1456.  
  1457.     case VERSION_OP:
  1458.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != EOF)
  1459.         opts.Language_Version = floatval;
  1460.       return;
  1461.  
  1462.     case BOUNDING_OP:
  1463.       opts.Use_Slabs = istrue(value);
  1464.       return;
  1465.  
  1466.     case BOUNDING_THRESH_OP:
  1467.       opts.BBox_Threshold = atoi(value);
  1468.       return;
  1469.  
  1470.     case QUALITY_OP:
  1471.       opts.Quality = atoi(value);
  1472.       /* Emit a warning about the "radiosity" quality levels for
  1473.        * now.  We can get rid of this some time in the future.
  1474.        */
  1475.       if ((opts.Quality == 10) || (opts.Quality == 11))
  1476.       {
  1477.          Warning(0.0, "Quality settings 10 and 11 are no longer valid.\n"
  1478.                       "Use +QR if you need radiosity.\n");
  1479.      opts.Quality = 9;
  1480.       }
  1481.       else if ((opts.Quality < 0) || (opts.Quality > 9))
  1482.       {
  1483.          Error("Illegal Quality setting.");
  1484.       }
  1485.       opts.Quality_Flags = Quality_Values[opts.Quality];
  1486.       return;
  1487.  
  1488.     case CLOCK_OP:
  1489.       if(sscanf (value, DBL_FORMAT_STRING, &floatval) != EOF)
  1490.       {
  1491.         opts.FrameSeq.Clock_Value = floatval;
  1492.       }
  1493.       return;
  1494.  
  1495.     case INITIAL_FRAME_OP:
  1496.       if(sscanf(value, "%ld", &longval)!=EOF)
  1497.       {
  1498.         opts.FrameSeq.InitialFrame=longval;
  1499.       }
  1500.       return;
  1501.  
  1502.     case INITIAL_CLOCK_OP:
  1503.       if(sscanf(value, DBL_FORMAT_STRING, &floatval)!=EOF)
  1504.       {
  1505.         opts.FrameSeq.InitialClock=floatval;
  1506.       }
  1507.       return;
  1508.  
  1509.     case FINAL_FRAME_OP:
  1510.       if(sscanf(value, "%ld", &longval)!=EOF)
  1511.       {
  1512.         opts.FrameSeq.FinalFrame=longval;
  1513.       }
  1514.       return;
  1515.  
  1516.     case FINAL_CLOCK_OP:
  1517.       if(sscanf(value, DBL_FORMAT_STRING, &floatval)!=EOF)
  1518.       {
  1519.         opts.FrameSeq.FinalClock=floatval;
  1520.       }
  1521.       return;
  1522.  
  1523.     case SUBSET_START_FRAME_OP:
  1524.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != EOF)
  1525.       {
  1526.         if(floatval > 0.0 && floatval < 1.0)
  1527.           opts.FrameSeq.SubsetStartPercent=floatval;
  1528.         else
  1529.           opts.FrameSeq.SubsetStartFrame=(int)floatval;
  1530.       }
  1531.       return;
  1532.  
  1533.     case SUBSET_END_FRAME_OP:
  1534.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != EOF)
  1535.       {
  1536.         if(floatval > 0.0 && floatval < 1.0)
  1537.           opts.FrameSeq.SubsetEndPercent=floatval;
  1538.         else
  1539.           opts.FrameSeq.SubsetEndFrame=(int)floatval;
  1540.       }
  1541.       return;
  1542.  
  1543.     case PREVIEW_S_OP:
  1544.       opts.PreviewGridSize_Start = atoi(value);
  1545.       return;
  1546.  
  1547.     case PREVIEW_E_OP:
  1548.       opts.PreviewGridSize_End = atoi(value);
  1549.       return;
  1550.  
  1551.     case CREATE_INI_OP:
  1552.       strcpy(opts.Ini_Output_File_Name,value);
  1553.       return;
  1554.  
  1555.     case ALL_CONSOLE_OP:
  1556.       Stream_Info[ALL_STREAM].do_console =
  1557.       Stream_Info[WARNING_STREAM].do_console =
  1558.       Stream_Info[STATISTIC_STREAM].do_console =
  1559.       Stream_Info[RENDER_STREAM].do_console = 
  1560.       Stream_Info[FATAL_STREAM].do_console = 
  1561.       Stream_Info[DEBUG_STREAM].do_console = istrue(value);
  1562.       return;
  1563.  
  1564.     case ALL_FILE_OP:
  1565.       Do_Stream_Option(ALL_STREAM,value);
  1566.       return;
  1567.  
  1568.     case DEBUG_CONSOLE_OP:
  1569.       Stream_Info[DEBUG_STREAM].do_console = istrue(value);
  1570.       return;
  1571.  
  1572.     case DEBUG_FILE_OP:
  1573.       Do_Stream_Option(DEBUG_STREAM,value);
  1574.       return;
  1575.  
  1576.     case FATAL_CONSOLE_OP:
  1577.       Stream_Info[FATAL_STREAM].do_console = istrue(value);
  1578.       return;
  1579.  
  1580.     case FATAL_FILE_OP:
  1581.       Do_Stream_Option(FATAL_STREAM,value);
  1582.       return;
  1583.  
  1584.     case RENDER_CONSOLE_OP:
  1585.       Stream_Info[RENDER_STREAM].do_console = istrue(value);
  1586.       return;
  1587.  
  1588.     case RENDER_FILE_OP:
  1589.       Do_Stream_Option(RENDER_STREAM,value);
  1590.       return;
  1591.  
  1592.     case STATISTIC_CONSOLE_OP:
  1593.       Stream_Info[STATISTIC_STREAM].do_console = istrue(value);
  1594.       return;
  1595.  
  1596.     case STATISTIC_FILE_OP:
  1597.       Do_Stream_Option(STATISTIC_STREAM,value);
  1598.       return;
  1599.  
  1600.     case WARNING_CONSOLE_OP:
  1601.       Stream_Info[WARNING_STREAM].do_console = istrue(value);
  1602.       return;
  1603.  
  1604.     case WARNING_FILE_OP:
  1605.       Do_Stream_Option(WARNING_STREAM,value);
  1606.       return;
  1607.  
  1608.     case RAD_SWITCH_OP:
  1609.       Option_Number = RADIOSITY;
  1610.       break;
  1611.  
  1612.     case HIST_SIZE_OP:
  1613.       if (sscanf (value, "%d.%d", &opts.histogram_x, &opts.histogram_y) == EOF)
  1614.       {
  1615.         Warning (0.0, "Error occurred scanning histogram grid size '%s'.\n", value) ;
  1616.         opts.histogram_on = FALSE ;
  1617.       }
  1618.       break ;
  1619.  
  1620.     case HIST_TYPE_OP:
  1621. #if PRECISION_TIMER_AVAILABLE
  1622.     {
  1623.       char *def_ext = NULL;
  1624.  
  1625.       switch (*value)
  1626.       {
  1627.         case 'C' :
  1628.         case 'c' :
  1629.              opts.histogram_on = TRUE ;
  1630.              opts.histogram_type = CSV ;
  1631.              def_ext = ".csv";
  1632.              break ;
  1633.         case 'S' :
  1634.         case 's' :
  1635.              opts.histogram_on = TRUE ;
  1636.              opts.histogram_type = SYS ;
  1637.              Histogram_File_Handle = GET_SYS_FILE_HANDLE () ;
  1638.              def_ext = SYS_DEF_EXT;
  1639.              break ;
  1640.         case 'P' :
  1641.         case 'p' :
  1642.              opts.histogram_on = TRUE ;
  1643.              opts.histogram_type = PPM ;
  1644.              Histogram_File_Handle = Get_PPM_File_Handle () ;
  1645.              def_ext = ".ppm";
  1646.              break ;
  1647.         case 'T' :
  1648.         case 't' :
  1649.              opts.histogram_on = TRUE ;
  1650.              opts.histogram_type = TARGA ;
  1651.              Histogram_File_Handle = Get_Targa_File_Handle () ;
  1652.              def_ext = ".tga";
  1653.              break ;
  1654.         case 'n':
  1655.         case 'N':
  1656.              opts.histogram_on = TRUE ;
  1657.              opts.histogram_type = PNG ;
  1658.              Histogram_File_Handle = Get_Png_File_Handle () ;
  1659.              def_ext = ".png";
  1660.              break ;
  1661.         case 'x':
  1662.         case 'X':
  1663.              opts.histogram_on = FALSE ;
  1664.              break ;
  1665.         default :
  1666.              Warning (0.0, "Unknown histogram output type '%c'.\n", *value) ;
  1667.              opts.histogram_on = FALSE ;
  1668.              break ;
  1669.       }
  1670.  
  1671.       /* Process the histogram file name now, if it hasn't
  1672.        * yet been specified, and in case it isn't set later.
  1673.        */
  1674.       if (opts.histogram_on && opts.Histogram_File_Name[0] == '\0')
  1675.       {
  1676.         sprintf(opts.Histogram_File_Name, "histgram%s", def_ext);
  1677.       }
  1678.     }
  1679. #else  /* !PRECISION_TIMER_AVAILABLE */
  1680.       if (*value != 'x' && *value != 'X')
  1681.         Warning(0.0,"Histogram output unavailable in this compile of POV-Ray");
  1682.       opts.histogram_on = FALSE;
  1683. #endif /* PRECISION_TIMER_AVAILABLE */
  1684.       break ;
  1685.  
  1686.     case HIST_NAME_OP:
  1687.       if (opts.histogram_on && value[0] == '\0')
  1688.       {
  1689.         char *def_ext = NULL;
  1690.  
  1691.         switch (opts.histogram_type)
  1692.         {
  1693.           case CSV:   def_ext = ".csv"; break;
  1694.           case TARGA: def_ext = ".tga"; break;
  1695.           case PNG:   def_ext = ".png"; break;
  1696.           case PPM:   def_ext = ".ppm"; break;
  1697.           case SYS:   def_ext = SYS_DEF_EXT; break;
  1698.           case NONE:  def_ext = "";     break;  /* To quiet warnings */
  1699.         }
  1700.  
  1701.         sprintf(opts.Histogram_File_Name, "histgram%s", def_ext);
  1702.       }
  1703.       else
  1704.       {
  1705.         strncpy (opts.Histogram_File_Name, value, FILE_NAME_LENGTH);
  1706.       }
  1707.       break ;
  1708.  
  1709.     case VISTA_BUFFER_OP:
  1710.       Option_Number = USE_VISTA_BUFFER;
  1711.       break;
  1712.  
  1713.     case LIGHT_BUFFER_OP:
  1714.       Option_Number = USE_LIGHT_BUFFER;
  1715.       break;
  1716.  
  1717.     case DRAW_VISTAS_OP:
  1718.       Option_Number = USE_VISTA_DRAW;
  1719.       break;
  1720.  
  1721.     case SPLIT_UNIONS_OP:
  1722.       Option_Number = SPLIT_UNION;
  1723.       break;
  1724.  
  1725.     case REMOVE_BOUNDS_OP:
  1726.       Option_Number = REMOVE_BOUNDS;
  1727.       break;
  1728.  
  1729.     case CYCLIC_ANIMATION_OP:
  1730.       Option_Number = CYCLIC_ANIMATION;
  1731.       break;
  1732.  
  1733.     case PRE_SCENE_CMD_OP:
  1734.       strcpy(opts.Shellouts[PRE_SCENE_SHL].Command, value);
  1735.       break;
  1736.  
  1737.     case PRE_FRAME_CMD_OP:
  1738.       strcpy(opts.Shellouts[PRE_FRAME_SHL].Command, value);
  1739.       break;
  1740.  
  1741.     case POST_FRAME_CMD_OP:
  1742.       strcpy(opts.Shellouts[POST_FRAME_SHL].Command, value);
  1743.       break;
  1744.  
  1745.     case POST_SCENE_CMD_OP:
  1746.       strcpy(opts.Shellouts[POST_SCENE_SHL].Command, value);
  1747.       break;
  1748.  
  1749.     case USER_ABORT_CMD_OP:
  1750.       strcpy(opts.Shellouts[USER_ABORT_SHL].Command, value);
  1751.       break;
  1752.  
  1753.     case FATAL_ERROR_CMD_OP:
  1754.       strcpy(opts.Shellouts[FATAL_SHL].Command, value);
  1755.       break;
  1756.  
  1757.     case PRE_SCENE_RET_OP:
  1758.       Do_Return_Option(PRE_SCENE_SHL, value);
  1759.       break;
  1760.  
  1761.     case PRE_FRAME_RET_OP:
  1762.       Do_Return_Option(PRE_FRAME_SHL, value);
  1763.       break;
  1764.  
  1765.     case POST_FRAME_RET_OP:
  1766.       Do_Return_Option(POST_FRAME_SHL, value);
  1767.       break;
  1768.  
  1769.     case POST_SCENE_RET_OP:
  1770.       Do_Return_Option(POST_SCENE_SHL, value);
  1771.       break;
  1772.  
  1773.     case USER_ABORT_RET_OP:
  1774.       Do_Return_Option(USER_ABORT_SHL, value);
  1775.       break;
  1776.  
  1777.     case FATAL_ERROR_RET_OP:
  1778.       Do_Return_Option(FATAL_SHL, value);
  1779.       break;
  1780.  
  1781.     case OUTPUT_ALPHA_OP:
  1782.       Option_Number = OUTPUT_ALPHA;
  1783.       break;
  1784.  
  1785.     case FIELD_RENDER_OP:
  1786.       opts.FrameSeq.Field_Render_Flag = istrue(value);
  1787.       return;
  1788.  
  1789.     case ODD_FIELD_OP:
  1790.       opts.FrameSeq.Odd_Field_Flag = istrue(value);
  1791.       return;
  1792.  
  1793.     case SAMPLING_METHOD_OP:
  1794.       opts.Tracing_Method = atoi(value);
  1795.       return;
  1796.  
  1797.     case BITS_PER_COLOR_OP:
  1798.     case BITS_PER_COLOUR_OP:
  1799.       opts.OutputQuality = atoi(value);
  1800.       opts.OutputQuality = max(5,  opts.OutputQuality);
  1801.       opts.OutputQuality = min(16, opts.OutputQuality);
  1802.       return;
  1803.  
  1804.     case DISPLAY_GAMMA_OP:
  1805.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != EOF)
  1806.       {
  1807.         if (floatval > 0.0)
  1808.           opts.DisplayGamma = floatval;
  1809.       }
  1810.       return;
  1811.  
  1812.     case INCLUDE_INI_OP:
  1813.       if (!parse_ini_file(value))
  1814.       {
  1815.         Error ("Could not open Include_Ini='%s'.\n", value);
  1816.       }
  1817.       return;
  1818.  
  1819.     default:
  1820.       Warning(0.0,"Unimplemented INI '%s'.\n",Option_Variable[variable].Token_Name);
  1821.       return;
  1822.  
  1823.   }
  1824.  
  1825.   if (Option_Number != 0)
  1826.   {
  1827.     if (istrue(value))
  1828.     {
  1829.       opts.Options |= Option_Number;
  1830.     }
  1831.     else
  1832.     {
  1833.       opts.Options &= ~Option_Number;
  1834.     }
  1835.   }
  1836. }
  1837.  
  1838.  
  1839.  
  1840. /*****************************************************************************
  1841. *
  1842. * FUNCTION
  1843. *
  1844. *   istrue
  1845. *
  1846. * INPUT
  1847. *   
  1848. * OUTPUT
  1849. *   
  1850. * RETURNS
  1851. *   
  1852. * AUTHOR
  1853. *
  1854. *   POV-Ray Team
  1855. *   
  1856. * DESCRIPTION
  1857. *
  1858. *   -
  1859. *
  1860. * CHANGES
  1861. *
  1862. *   -
  1863. *
  1864. ******************************************************************************/
  1865.  
  1866. static int matches(v1,v2)
  1867. char *v1, *v2;
  1868. {
  1869.   int i=0;
  1870.   int ans=TRUE;
  1871.   
  1872.   while ((ans) && (v1[i] != '\0') && (v2[i] != '\0'))
  1873.   {
  1874.     ans = ans && (v1[i] == tolower(v2[i]));
  1875.     i++;
  1876.   }
  1877.   
  1878.   return(ans);
  1879. }
  1880.  
  1881. static int istrue(value)
  1882. char *value;
  1883. {
  1884.    return (matches("on",value)  || matches("true",value) || 
  1885.            matches("yes",value) || matches("1",value));
  1886. }
  1887.  
  1888. static int isfalse(value)
  1889. char *value;
  1890. {
  1891.    return (matches("off",value)  || matches("false",value) || 
  1892.            matches("no",value)   || matches("0",value));
  1893. }
  1894.  
  1895.  
  1896. /*****************************************************************************
  1897. *
  1898. * FUNCTION
  1899. *
  1900. *   Write_INI_File
  1901. *
  1902. * INPUT
  1903. *   
  1904. * OUTPUT
  1905. *   
  1906. * RETURNS
  1907. *   
  1908. * AUTHOR
  1909. *
  1910. *   SCD, 2/95
  1911. *   
  1912. * DESCRIPTION
  1913. *
  1914. *   Writes all options to an INI file with the current input filename's name
  1915. *   (by default), or using a specified filename.
  1916. *
  1917. * CHANGES
  1918. *
  1919. *   -
  1920. *
  1921. ******************************************************************************/
  1922.  
  1923. void Write_INI_File()
  1924. {
  1925.   int  op, i;
  1926.   char ini_name[FILE_NAME_LENGTH];
  1927.   FILE *ini_file;
  1928.  
  1929.   if (opts.Ini_Output_File_Name[0]=='\0')
  1930.   {
  1931.     return;
  1932.   }
  1933.  
  1934.   if (isfalse(opts.Ini_Output_File_Name))
  1935.   {
  1936.     return;
  1937.     }
  1938.  
  1939.   Status_Info("\nWriting INI file...");
  1940.  
  1941.   if (istrue(opts.Ini_Output_File_Name))
  1942.       {
  1943.     strcpy(ini_name,opts.Scene_Name);
  1944.     strcat(ini_name,".ini");
  1945.       }
  1946.       else
  1947.       {
  1948.     strcpy(ini_name,opts.Ini_Output_File_Name);
  1949.   }
  1950.  
  1951.   if ((ini_file = fopen(ini_name, WRITE_FILE_STRING)) == NULL)
  1952.   {
  1953.     Warning (0.0,"Error opening .INI output file '%s' - no file written.\n",
  1954.                     ini_name);
  1955.  
  1956.     return;
  1957.   }
  1958.  
  1959.   for (op = 0; op < MAX_OPTION; op++)
  1960.   {
  1961.     if (op == LIBRARY_PATH_OP)
  1962.     {
  1963.       for (i = 0; i < opts.Library_Path_Index; i++)
  1964.       {
  1965.         fprintf(ini_file,"%s=%s%s",Option_Variable[op].Token_Name,
  1966.                    get_ini_value(op, i),NEW_LINE_STRING);
  1967.       }
  1968.     }
  1969.     /* So that we don't get both Bits_Per_Color and Bits_Per_Colour in
  1970.      * the INI file. */
  1971.     else if ((op != BITS_PER_COLOUR_OP) && (op != INCLUDE_INI_OP))
  1972.     {
  1973.       fprintf(ini_file,"%s=%s%s",Option_Variable[op].Token_Name,
  1974.                    get_ini_value(op, 0),NEW_LINE_STRING);
  1975.     }
  1976.   }
  1977.  
  1978.   fclose(ini_file);
  1979. }
  1980.  
  1981.  
  1982.  
  1983. /*****************************************************************************
  1984. *
  1985. * FUNCTION
  1986. *
  1987. *   parse_ini_file
  1988. *
  1989. * INPUT
  1990. *   
  1991. * OUTPUT
  1992. *   
  1993. * RETURNS
  1994. *   
  1995. * AUTHOR
  1996. *
  1997. *   POV-Ray Team
  1998. *   
  1999. * DESCRIPTION
  2000. *
  2001. *   Given a file name, open it, parse options from it, close it.
  2002. *   Return 1 if file found, 0 if not found.
  2003. *
  2004. * CHANGES
  2005. *
  2006. *   -
  2007. *
  2008. ******************************************************************************/
  2009.  
  2010. int parse_ini_file(File_Name)
  2011. char *File_Name;
  2012. {
  2013.   char Option_Line[512];
  2014.   char INI_Name[FILE_NAME_LENGTH];
  2015.   char Desired_Section[FILE_NAME_LENGTH];
  2016.   char Current_Section[FILE_NAME_LENGTH];
  2017.   char *source, *dest;
  2018.   FILE *ini_file;
  2019.   int Matched, Never_Matched;
  2020.  
  2021.   Stage=STAGE_INI_FILE;
  2022.   
  2023.   /* File_Name can be of the for "FILE.INI[Section]" where everything
  2024.    * before the '[' is the actual name and "[Section]" is the title of
  2025.    * a section within that file that starts with the [Section] heading.  
  2026.    * Only the specified section of the INI file is processed.  If no
  2027.    * section is specified then only parts of the file without a section
  2028.    * header are processed.
  2029.    */
  2030.    
  2031.   /* Copy the file name part */
  2032.   source=File_Name;
  2033.   dest=INI_Name;
  2034.   while ((*source != '\0') && (*source != '['))
  2035.   {
  2036.     *(dest++) = *(source++);
  2037.   }
  2038.   *dest = '\0';
  2039.  
  2040.   /* Copy the section name part */
  2041.   dest = Desired_Section;
  2042.   while ((*source != '\0') && (*source != ']'))
  2043.   {
  2044.     *(dest++) = *(source++);
  2045.   }
  2046.   *dest = *source;
  2047.   *(++dest)='\0';
  2048.  
  2049.   if ((ini_file = Locate_File(INI_Name, READ_FILE_STRING,".ini",".INI",FALSE)) == NULL)
  2050.   {
  2051.     return(FALSE);
  2052.   }
  2053.  
  2054.   *Current_Section='\0';
  2055.   
  2056.   Matched = (*Desired_Section == '\0');
  2057.   Never_Matched=TRUE;
  2058.   
  2059.   while (fgets(Option_Line, 512, ini_file) != NULL)
  2060.   {
  2061.     if (*Option_Line == '[')
  2062.     {
  2063.       source=Option_Line;
  2064.       dest=Current_Section;
  2065.       while ((*source != '\0') && (*source != ']'))
  2066.       {
  2067.         *(dest++) = *(source++);
  2068.       }
  2069.       *dest = *source;
  2070.       *(++dest)='\0';
  2071.       Matched = (pov_stricmp(Current_Section, Desired_Section) == 0);
  2072.       
  2073.     }
  2074.     else
  2075.     {    
  2076.        if (Matched)
  2077.        {
  2078.           parse_option_line(Option_Line);
  2079.           Never_Matched=FALSE;
  2080.        }
  2081.     }
  2082.   }
  2083.  
  2084.   if (Never_Matched)
  2085.   {
  2086.      Warning(0.0,"Never found section %s in file %s.\n",Desired_Section,INI_Name);
  2087.   }
  2088.   
  2089.   fclose(ini_file);
  2090.  
  2091.   return(TRUE);
  2092. }
  2093.  
  2094.  
  2095. /*****************************************************************************
  2096. *
  2097. * FUNCTION
  2098. *
  2099. *   parse_option_line
  2100. *
  2101. * INPUT
  2102. *   
  2103. * OUTPUT
  2104. *   
  2105. * RETURNS
  2106. *   
  2107. * AUTHOR
  2108. *
  2109. *   POV-Ray Team
  2110. *   
  2111. * DESCRIPTION
  2112. *
  2113. *   Given a string containing a line of text, split it into individual
  2114. *   switches or options and then pass them off to be parsed by parse_switch
  2115. *   or process_variable.  This routine is called by parse_ini_file,
  2116. *   by the main with argv[] and by READ_ENV_VAR_????
  2117. *
  2118. * CHANGES
  2119. *
  2120. *   Mar 1996 : Allow ';' in an option, if it is escaped  [AED]
  2121. *
  2122. ******************************************************************************/
  2123.  
  2124. void parse_option_line(Option_Line)
  2125. char *Option_Line;
  2126. {
  2127.   char *source, *dest;
  2128.   char Option_String[512];
  2129.   int i,Found;
  2130.  
  2131.   source =  Option_Line;
  2132.  
  2133.   while (TRUE)
  2134.   {
  2135.     /* skip leading white space */
  2136.     while (((int)*source > 0) && ((int)*source < 33))
  2137.     {
  2138.       source++;
  2139.     }
  2140.  
  2141.     /* Quit when finished or ignore if commented */
  2142.     if ((*source == '\0') || (*source == ';'))
  2143.     {
  2144.       return;
  2145.     }
  2146.     
  2147.     if ((*source == '=') || (*source == '#'))
  2148.     {
  2149.       Error("'=' or '#' must be preceded by a keyword.");
  2150.     }
  2151.  
  2152.     /* Copy everything that is not a space, an equals or a comment 
  2153.        into Option_String 
  2154.     */
  2155.     dest = Option_String;
  2156.     while ((isprint((int)*source)) && 
  2157.            (*source != ' ') && 
  2158.            (*source != '=') && 
  2159.            (*source != '#') && 
  2160.            (*source != ';'))
  2161.     {
  2162.       *(dest++) = *(source++);
  2163.     }
  2164.     *dest = '\0';
  2165.  
  2166.     /* If its a +/- style switch then just do it */
  2167.     if ((*Option_String == '+') || (*Option_String == '-'))
  2168.     {
  2169.       parse_switch(Option_String);
  2170.       continue;
  2171.     }
  2172.  
  2173.         /* Now search the Option_Variables to see if we find a match */
  2174.  
  2175.     Found=-1;
  2176.     for (i = 0 ; i < MAX_OPTION; i++)
  2177.     {
  2178.       if (pov_stricmp(Option_Variable[i].Token_Name, Option_String) == 0)
  2179.       {
  2180.         Found=Option_Variable[i].Token_Number;
  2181.         break;
  2182.       }
  2183.     }
  2184.     
  2185.     if (Found<0)
  2186.     {
  2187.       /* When an option string does not begin with a '+' or '-', and
  2188.        * is not in the list of valid keywords, then it is assumed to 
  2189.        * be a file name.  Most such file names are .INI/.DEF files to 
  2190.        * be parsed.  However the syntax for the +I and the +O 
  2191.        * command-line switches, allows a space to appear between the 
  2192.        * switch and the name.  For example: "+I MYFILE.POV" is legal.  
  2193.        * The flags inflag and outflag indicate that there was a +I 
  2194.        * or +O switch parsed just before this file name.
  2195.        */
  2196.  
  2197.       if (inflag)
  2198.       {
  2199.         strncpy (opts.Input_File_Name, Option_String, FILE_NAME_LENGTH);
  2200.         inflag = FALSE;
  2201.         continue;
  2202.       }
  2203.  
  2204.       if (outflag)
  2205.       {
  2206.         strncpy (opts.Output_File_Name, Option_String, FILE_NAME_LENGTH);
  2207.         outflag = FALSE;
  2208.         continue;
  2209.       }
  2210.       
  2211.       /* If the keyword didn't match and it wasn't an inflag/outflag
  2212.        * thing, then its either a .INI/.DEF file or its an error.
  2213.        */
  2214.        
  2215.       if (++Number_Of_Files > MAX_NESTED_INI)
  2216.       {
  2217.         Error ("Bad option syntax or too many nested .INI/.DEF files.");
  2218.       }
  2219.  
  2220.       if (!parse_ini_file(Option_String))
  2221.       {
  2222.         Error ("Bad option syntax or error opening .INI/.DEF file '%s'.\n", Option_String);
  2223.       }
  2224.       continue;
  2225.     }
  2226.     
  2227.     /* If we make it this far, then it must be an .INI-style setting with
  2228.      * the keyword already verified in "Found".  We now need to verify that
  2229.      * an equals sign follows.  
  2230.      */
  2231.  
  2232.     /* skip white space */
  2233.     while (((int)*source > 0) && ((int)*source < 33))
  2234.     {
  2235.       source++;
  2236.     }
  2237.     
  2238.     if ((*source != '=') && (*source != '#'))
  2239.     {
  2240.       Error("Missing '=' or '#' after %s in option.",Option_String);
  2241.     }
  2242.     
  2243.     source++;
  2244.  
  2245.     /* Now the entire rest of Option_Line up to but excluding a comment, 
  2246.      * becomes the variable part of the option. 
  2247.      */
  2248.  
  2249.     /* skip white space */
  2250.     while (((int)*source > 0) && ((int)*source < 33))
  2251.     {
  2252.       source++;
  2253.     }
  2254.     
  2255.     dest=source;
  2256.     
  2257.     /* Cut off comments and any unprintable characters */
  2258.     while (*source != '\0') 
  2259.     {
  2260.        /* If the comment character is escaped, pass it through */
  2261.        if ((*source == '\\') && (*(source + 1) == ';'))
  2262.        {
  2263.          *source = ';';
  2264.          source++;
  2265.          *source = ' ';
  2266.          source++;
  2267.        }
  2268.        else if ((*source == ';') || (! isprint((int)*source) ) )
  2269.        {
  2270.          *source = '\0';
  2271.        }
  2272.        else
  2273.        {
  2274.          source++;
  2275.        }
  2276.     }
  2277.     process_variable(Found, dest);
  2278.     return;
  2279.   }
  2280. }
  2281.  
  2282.  
  2283.  
  2284. /*****************************************************************************
  2285. *
  2286. * FUNCTION
  2287. *
  2288. * INPUT
  2289. *   
  2290. * OUTPUT
  2291. *   
  2292. * RETURNS
  2293. *   
  2294. * AUTHOR
  2295. *   
  2296. * DESCRIPTION
  2297. *
  2298. * CHANGES
  2299. *
  2300. ******************************************************************************/
  2301.  
  2302. void Do_Stream_Option (i, value)
  2303. int i;
  2304. char *value;
  2305. {
  2306.   if (value==NULL)
  2307.   {
  2308.     return;
  2309.   }
  2310.  
  2311.   if (*value == '\0')
  2312.   {
  2313.     return;
  2314.   }
  2315.  
  2316.   if (Stream_Info[i].name != NULL)
  2317.   {
  2318.     POV_FREE(Stream_Info[i].name);
  2319.  
  2320.     Stream_Info[i].name = NULL;
  2321.   }
  2322.  
  2323.   if (istrue(value))
  2324.   {
  2325.     Stream_Info[i].name = POV_MALLOC(strlen(DefaultFile[i])+1, "stream name");
  2326.  
  2327.     strcpy(Stream_Info[i].name, DefaultFile[i]);
  2328.   }
  2329.   else
  2330.   {
  2331.     if (isfalse(value))
  2332.     {
  2333.       return;
  2334.     }
  2335.  
  2336.     Stream_Info[i].name = POV_MALLOC(strlen(value)+1, "stream name");
  2337.  
  2338.     strcpy(Stream_Info[i].name, value);
  2339.  }
  2340. }
  2341.  
  2342.  
  2343.  
  2344. /*****************************************************************************
  2345. *
  2346. * FUNCTION
  2347. *
  2348. * INPUT
  2349. *   
  2350. * OUTPUT
  2351. *   
  2352. * RETURNS
  2353. *   
  2354. * AUTHOR
  2355. *   
  2356. * DESCRIPTION
  2357. *
  2358. * CHANGES
  2359. *
  2360. ******************************************************************************/
  2361.  
  2362. void Do_Return_Option (Type, value)
  2363. SHELLTYPE Type;
  2364. char *value;
  2365. {
  2366.    char *s;
  2367.    
  2368.    SHELLDATA *Shell=&(opts.Shellouts[Type]);
  2369.    
  2370.    Shell->Inverse=FALSE;
  2371.    Shell->Ret=IGNORE_RET;
  2372.    
  2373.    if (value==NULL)
  2374.      return;
  2375.      
  2376.    if (*value=='\0')
  2377.      return;
  2378.      
  2379.    if ((*value=='-') || (*value=='!'))
  2380.    {
  2381.       Shell->Inverse=TRUE;
  2382.       value++;
  2383.    }
  2384.  
  2385.    if (*value=='\0')
  2386.      return;
  2387.  
  2388.    if ((s=strchr(ret_string,toupper(*value))) == NULL)
  2389.    {
  2390.      Warning(0.0,"Bad value in shellout return '%c'. Only '%s' are allowed.\n",*value,ret_string);
  2391.      Shell->Ret = IGNORE_RET;
  2392.    }
  2393.    else
  2394.    {
  2395.      Shell->Ret = (SHELLRET)(s-ret_string);
  2396.    }
  2397. }
  2398.